using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;

//表示一个背包系统
[System.Serializable]
public class InventorySystem
{
    [SerializeField] private List<InventorySlot> inventorySlots;//存储背包中的物品槽位
    [SerializeField] private int _gold;
    public int Gold => _gold;
    public List<InventorySlot> InventorySlots => inventorySlots;//用于访问和编辑背包中的物品槽位cc
    public int InventorySize => InventorySlots.Count;//获取背包的大小（即物品槽位的数量）
    public UnityAction<InventorySlot> OnInventorySlotChanged;//当背包中的物品槽位发生变化时会触发该事件，并传递被修改的物品槽位作为参数。

    //用于创建一个具有指定大小的背包系统
    public InventorySystem(int size)
    {
        _gold = 0;
        CreateInventory(size);
    }
    public InventorySystem(int size, int gold)
    {
        _gold = gold;
        CreateInventory(size);
    }

    private void CreateInventory(int size)
    {
        //根据指定的大小创建对应数量的空物品槽位
        inventorySlots = new List<InventorySlot>(size);
        for (int i = 0; i < size; i++)
        {
            inventorySlots.Add(new InventorySlot());
        }
    }

    // 向背包添加物品
    public bool AddToInventory(InventoryItemData itemToAdd, int amountToAdd)
    {
        if (ContainsItem(itemToAdd, out List<InventorySlot> invSlots)) // 检查物品是否存在于库存中
        {
            foreach (var slot in invSlots)
            {
                if (slot.EnoughRoomLeftInStack(amountToAdd)) // 如果库存槽剩余空间足够
                {
                    slot.AddToStack(amountToAdd); // 将物品添加到堆叠
                    OnInventorySlotChanged?.Invoke(slot); // 触发库存槽变化事件
                    return true;
                }
            }
        }

        if (HasFreeSlot(out InventorySlot freeSlot)) // 获取第一个可用的库存槽
        {
            if (freeSlot.EnoughRoomLeftInStack(amountToAdd))
            {
                freeSlot.UpdateInventorySlot(itemToAdd, amountToAdd); // 更新库存槽
                OnInventorySlotChanged?.Invoke(freeSlot); // 触发库存槽变化事件
                return true;
            }
        }

        return false;
    }

    //检查库存槽列表中是否存在与要添加的物品匹配的库存槽
    public bool ContainsItem(InventoryItemData itemToAdd, out List<InventorySlot> invSlots)
    {
        // 在库存槽列表中查找与要添加的物品匹配的库存槽
        invSlots = InventorySlots.Where(slot => slot.ItemData == itemToAdd).ToList();

        // return invSlots != null && invSlots.Count > 0; // 返回是否存在匹配的库存槽
        return invSlots == null ? false : true; // 返回是否存在匹配的库存槽
    }

    //用于查找第一个物品为空的库存槽
    public bool HasFreeSlot(out InventorySlot freeSlot)
    {
        // 查找第一个物品为空的库存槽
        freeSlot = InventorySlots.FirstOrDefault(slot => slot.ItemData == null);

        return freeSlot != null; // 返回是否存在可用的库存槽
    }

    /// <summary>
    /// 检查背包剩余空间是否足够容纳购物车中的物品
    /// </summary>
    /// <param name="shoppingCart">购物车字典，键为物品数据，值为物品数量</param>
    /// <returns>如果背包剩余空间足够容纳购物车中的物品，则返回true；否则返回false</returns>
    public bool CheckInventoryRemaining(Dictionary<InventoryItemData, int> shoppingCart)
    {
        var clonedSystem = new InventorySystem(InventorySize);// 克隆一个背包系统
        for (int i = 0; i < InventorySize; i++)
        {
            // 将当前背包的物品信息复制到克隆的背包系统中
            clonedSystem.InventorySlots[i].AssignItem(InventorySlots[i].ItemData, InventorySlots[i].StackSize);
        }
        foreach (var kvp in shoppingCart)// 遍历购物车中的物品
        {
            for (int i = 0; i < kvp.Value; i++)// 遍历购物车中每种物品的数量
            {
                // 尝试将物品添加到克隆的背包系统中，如果添加失败（即背包空间不足），则返回false
                if (!clonedSystem.AddToInventory(kvp.Key, 1)) return false;
            }
        }
        // 所有物品都能成功添加到背包中，则返回true
        return true;
    }

    public void SpendGold(int basketTotal)
    {
        // 从玩家金币中扣除购物车总额
        _gold -= basketTotal;
    }

    //获取玩家库存中所有持有的物品及其数量的方法
    public Dictionary<InventoryItemData, int> GetAllItemsHeld()
    {
        var distinctItems = new Dictionary<InventoryItemData, int>();
        foreach (var item in inventorySlots)
        {
            if (item.ItemData == null) continue;// 如果物品数据为空，跳过当前循环
            if (!distinctItems.ContainsKey(item.ItemData)) distinctItems.Add(item.ItemData, item.StackSize);// 如果字典中不存在该物品数据，则添加到字典中
            else distinctItems[item.ItemData] += item.StackSize; // 否则，增加物品数量
        }
        return distinctItems;
    }

    // 玩家增加金币
    public void GainGold(int price)
    {
        _gold += price;
    }

    //从库存中移除物品
    public void RemoveItemsFromInventory(InventoryItemData data, int amount)
    {
        // 检查库存中是否包含指定物品，并获取包含该物品的所有库存槽
        if (ContainsItem(data, out List<InventorySlot> inventorySlots))
        {
            foreach (var slot in inventorySlots)
            {
                var stackSize = slot.StackSize;
                if (stackSize > amount)
                {
                    // 如果库存槽中的堆叠大小 大于 要移除的数量，则从堆叠中移除指定数量的物品
                    slot.RemoveFromStack(amount);
                    // 触发库存槽变化事件
                    OnInventorySlotChanged?.Invoke(slot);
                    return;
                }
                else
                {
                    // 否则则从堆叠中移除全部物品，并更新剩余数量
                    slot.RemoveFromStack(stackSize);
                    amount -= stackSize;
                    // 触发库存槽变化事件
                    OnInventorySlotChanged?.Invoke(slot);
                }
            }
        }
    }
}
